using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using System.Xml;

namespace stsdev {

  public enum FeatureScopeEnum {
    Farm,
    WebApplication,
    Site,
    Web
  }

  public delegate void ElementWriterDelegate(XmlWriter writer);

  public class FeatureBuilder {

    private static string SolutionSpecificFeatureFolder = Globals.FeaturesFolder + @"\" + SolutionBuilder.SolutionName;
    private static List<string> ElementManifests = new List<string>();
    private static List<string> ElementFiles = new List<string>();

    public static void EnsureSolutionFolder() {
      // create \TEMPLATE Folder
      if (!Directory.Exists(Globals.TemplatesFolder)) {
        Directory.CreateDirectory(Globals.TemplatesFolder);
      }
      // create \TEMPLATE\FEATURE Folder
      if (!Directory.Exists(Globals.FeaturesFolder)) {
        Directory.CreateDirectory(Globals.FeaturesFolder);
      }
      // create project-specific Feature Folder
      if (!Directory.Exists(SolutionSpecificFeatureFolder)) {
        Directory.CreateDirectory(SolutionSpecificFeatureFolder);
      }
    }

    public static void CreateElementManifest(string ElementManifestFileName) {
      CreateElementManifest(ElementManifestFileName, null);
    }

    public static void CreateElementManifest(string ElementManifestFileName, ElementWriterDelegate ElementsWriterCallback) {
      EnsureSolutionFolder();
      StreamWriter manifestStream = 
        new StreamWriter(SolutionSpecificFeatureFolder + @"\" + 
                         ElementManifestFileName);
      XmlWriterSettings settings = new XmlWriterSettings();
      settings.Encoding = Encoding.UTF8;
      settings.Indent = true;
      settings.NewLineOnAttributes = false;
      settings.NewLineHandling = NewLineHandling.None;
      XmlWriter writer = XmlWriter.Create(manifestStream, settings);
      writer.WriteStartDocument();

      writer.WriteComment("Created by STSDEV at " + DateTime.Now.ToString());
      writer.WriteStartElement("Elements", Globals.SharePointNamespace);

      if (ElementsWriterCallback == null) {
        writer.WriteComment("TODO: add feature elements here");
      }
      else {
        ElementsWriterCallback(writer);
      }

      writer.WriteEndElement(); // </Elements>
      writer.WriteEndDocument();
      writer.Close();
      manifestStream.Close();
      // add ElementManifest file to ElementManifests collection
      ElementManifests.Add(ElementManifestFileName);
      ProjectFileBuilder.AddSourceFile(SolutionSpecificFeatureFolder + @"\" +
                                       ElementManifestFileName, 
                                       SourceFileTypeEnum.None);
    }

    public static void AddElementManifest(string ElementManifestFilePath) {
      ElementManifests.Add(ElementManifestFilePath);
    }

    public static void AddElementFile(string ElementFile) {
      ElementFiles.Add(ElementFile);
    }

    public static void Create(string FeatureName) {
      Create(FeatureName, FeatureScopeEnum.Web);
    }

    public static void Create(string FeatureName, FeatureScopeEnum FeatureScope) {
      Create(FeatureName, FeatureScope, true);
    }

    public static void Create(string FeatureName, FeatureScopeEnum FeatureScope, Boolean IncludeFeatureReceiver) {
      
      // add default image url
      string SolutionSpecificImagesDirectory = Globals.ImagesFolder + @"\" + SolutionBuilder.SolutionName;
      string DefaultImageUrl = SolutionSpecificImagesDirectory + @"\AfricanPith32.gif";
      if (!File.Exists(DefaultImageUrl)) {        
        // create /IMAGES directory if it doesn't exist
        if (!Directory.Exists(Globals.ImagesFolder)) {
          Directory.CreateDirectory(Globals.ImagesFolder);
        }
        // create solution-specific images directory if it doesn't exist        
        if (!Directory.Exists(SolutionSpecificImagesDirectory)) {
          Directory.CreateDirectory(SolutionSpecificImagesDirectory);
        }
        // add default image file for Feature ImageUrl
        Properties.Resources.AfricanPith32.Save(DefaultImageUrl);
        ProjectFileBuilder.AddSourceFile(DefaultImageUrl, SourceFileTypeEnum.None);
      }
      Create(FeatureName, FeatureScope, IncludeFeatureReceiver, DefaultImageUrl);
    }

    public static void Create(string FeatureName, FeatureScopeEnum FeatureScope, Boolean IncludeFeatureReceiver, string ImageUrl) {
      EnsureSolutionFolder();
      string FeatureXmlFilePath = SolutionSpecificFeatureFolder + @"\feature.xml";
      StreamWriter manifestStream = new StreamWriter(FeatureXmlFilePath);
      XmlWriterSettings settings = new XmlWriterSettings();
      settings.Encoding = Encoding.UTF8;
      settings.Indent = true;
      settings.NewLineOnAttributes = true;
      settings.NewLineHandling = NewLineHandling.None;
      XmlWriter writer = XmlWriter.Create(manifestStream, settings);
      writer.WriteStartDocument();

      writer.WriteComment("Created by STSDEV at " + DateTime.Now.ToString());
      writer.WriteStartElement("Feature", Globals.SharePointNamespace);
      // add solution ID
      writer.WriteAttributeString("Id", Guid.NewGuid().ToString().ToUpper());
      writer.WriteAttributeString("Title", "A sample feature: " + SolutionBuilder.SolutionName);
      writer.WriteAttributeString("Description", "This SharePoint solution was created by the STSDEV utility (http://codeplex.com/stsdev)");
      writer.WriteAttributeString("Version", "1.0.0.0");
      writer.WriteAttributeString("Scope", FeatureScope.ToString());
      writer.WriteAttributeString("Hidden", "false");
      // parse out ImageUrl path that is relative to IMAGES\ directory
      string OffsetText = @"IMAGES\";
      ImageUrl = ImageUrl.Substring(ImageUrl.IndexOf(OffsetText) + OffsetText.Length);
      writer.WriteAttributeString("ImageUrl", ImageUrl);
      if (IncludeFeatureReceiver) {
        CreateFeatureReceiver(); // create FeatureReceiver.cs
        writer.WriteAttributeString("ReceiverAssembly", SolutionBuilder.FullAssemblyName);
        writer.WriteAttributeString("ReceiverClass", SolutionBuilder.TargetName + ".FeatureReceiver");
      }

      if (ElementManifests.Count > 0 || ElementFiles.Count > 0) {
        writer.WriteStartElement("ElementManifests");
        // add element manifests
        foreach (string ElementManifest in ElementManifests) {
          writer.WriteStartElement("ElementManifest");
          writer.WriteAttributeString("Location", ElementManifest);
          writer.WriteEndElement(); // </ElementManifest>
        }
        // add element files
        foreach (string ElementFile in ElementFiles) {
          writer.WriteStartElement("ElementFile");
          writer.WriteAttributeString("Location", ElementFile);
          writer.WriteEndElement(); // </ElementManifest>
        }        
        writer.WriteEndElement(); // </ElementManifests>
      }

      writer.WriteEndElement(); // </Feature>
      writer.WriteEndDocument();
      writer.Close();
      manifestStream.Close();
      ProjectFileBuilder.AddSourceFile(FeatureXmlFilePath, SourceFileTypeEnum.None);
    }

    private static void CreateFeatureReceiver() {
      if (!File.Exists("FeatureReceiver.cs")) {
        FileStream FeatureReceiver_cs = File.Create("FeatureReceiver.cs");
        StreamWriter FeatureReceiver_writer = new StreamWriter(FeatureReceiver_cs);
        string FeatureReceiverCode = Properties.Resources.FeatureReceiver_cs;
        FeatureReceiverCode = FeatureReceiverCode.Replace("@SolutionName", SolutionBuilder.SolutionName);
        FeatureReceiver_writer.Write(FeatureReceiverCode);
        FeatureReceiver_writer.Dispose();
        FeatureReceiver_cs.Dispose();
        ProjectFileBuilder.AddSourceFile("FeatureReceiver.cs");
      }

    }
  }
}
